package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/go-stomp/stomp"
)

const (
	accessKey         = "LTAI5tD3xpxerdxSZ9q8XAJp"
	accessSecret      = "9GiuplYTm1791ZlPweci4KlKOl5pRN"
	iotInstanceId     = "iot-010a0clt"
	clientId          = "4C4C4544-0058-4A10-804D-CAC04F4D4D8P"
	baseURL           = "https://elder.fanmiot.cn"
	consumerGroupId   = "8P0bGLxHl0tyUXYrUlq0000110"
	amqpHost          = "iot-010a0clt.amqp.iothub.aliyuncs.com"
	amqpPort          = 61614
	heartbeatInterval = 300 * time.Second
)

// 获取当前时间戳（毫秒）
func currentTimeMillis() string {
	return fmt.Sprintf("%d", time.Now().UnixMilli())
}

// 生成身份认证凭据
func generateAuthCredentials() (string, string, error) {
	timestamp := currentTimeMillis()
	username := fmt.Sprintf("%s|authMode=aksign,signMethod=hmacsha1,timestamp=%s,authId=%s,iotInstanceId=%s,consumerGroupId=%s|",
		clientId, timestamp, accessKey, iotInstanceId, consumerGroupId)
	signContent := fmt.Sprintf("authId=%s&timestamp=%s", accessKey, timestamp)
	password, err := doSign([]byte(accessSecret), []byte(signContent))
	if err != nil {
		return "", "", err
	}
	return username, password, nil
}

// HMAC-SHA1 签名生成
func doSign(secret, content []byte) (string, error) {
	h := hmac.New(sha1.New, secret)
	if _, err := h.Write(content); err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
}

// 实时消息监听器
type RealTimeListener struct {
	conn *stomp.Conn
}

// 处理收到的消息
func (r *RealTimeListener) OnMessage(msg *stomp.Message) {
	log.Printf("收到消息: %s", string(msg.Body))
	response, err := http.Post(fmt.Sprintf("%s/xkl/warn/api", baseURL), "application/json", bytes.NewReader(msg.Body))
	if err != nil {
		log.Printf("处理消息失败: %v", err)
		return
	}
	defer response.Body.Close()
	if response.StatusCode != http.StatusOK {
		log.Printf("处理消息返回非预期状态码: %d", response.StatusCode)
	} else {
		log.Println("消息处理成功。")
	}
}

// 连接并订阅消息
func connectAndSubscribe() (*stomp.Conn, error) {
	username, password, err := generateAuthCredentials()
	if err != nil {
		return nil, fmt.Errorf("生成认证凭据失败: %w", err)
	}

	log.Printf("尝试连接，用户名: %s", username)
	conn, err := stomp.Dial("tcp",
		fmt.Sprintf("%s:%d", amqpHost, amqpPort),
		stomp.ConnOpt.Login(username, password),
		stomp.ConnOpt.HeartBeat(heartbeatInterval, heartbeatInterval))
	if err != nil {
		return nil, fmt.Errorf("连接失败: %w", err)
	}

	sub, err := conn.Subscribe("/topic/#", stomp.AckAuto)
	if err != nil {
		return nil, fmt.Errorf("订阅失败: %w", err)
	}

	go func() {
		for msg := range sub.C {
			listener := &RealTimeListener{conn: conn}
			listener.OnMessage(msg)
		}
	}()

	log.Println("订阅成功。")
	return conn, nil
}

// 主函数
func main() {
	var conn *stomp.Conn
	var err error

	// 重试机制，直到连接成功
	for {
		conn, err = connectAndSubscribe()
		if err == nil {
			break
		}
		log.Printf("连接失败: %v。5 秒后重试...", err)
		time.Sleep(5 * time.Second)
	}
	// 捕获系统信号（Ctrl+C 或终止信号）
	signalChan := make(chan os.Signal, 1)
	//signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)

	go func() {
		<-signalChan
		log.Println("接收到退出信号，正在关闭服务...")
		if conn != nil {
			conn.Disconnect()
		}
		os.Exit(0)
	}()

	// 阻塞主线程，保持服务运行
	select {}
}
